refactor(types): replace schemaMigrationPhase magic strings with an enum#65
Merged
Merged
Conversation
Introduce a SchemaMigrationPhase enum to replace the Option<String>
that has been growing magic-string call sites. Variants: Active,
Complete, Partial, TimeoutSkipped, Failed(String). The wire format is
preserved exactly (custom Serialize/Deserialize via Display/FromStr)
so existing replica status objects round-trip unchanged, and the CRD
field continues to declare a plain string via a custom JsonSchema
impl.
Motivation is the sweep-gate deadlock fix landed separately: the old
allow-list shape ("phase == complete | partial") silently broke when
the timeout-skipped phase was added, since the allow-list missed the
new variant. The replacement gate (is_settled()) is exhaustive over
the enum and the compiler now catches the next variant that forgets
to handle this — turning a runtime deadlock into a compile error.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖
Summary
Replace the `Option` shape of `PostgresPhysicalReplicaStatus.schemaMigrationPhase` with a proper enum:
```rust
pub enum SchemaMigrationPhase {
Active,
Complete,
Partial,
TimeoutSkipped,
Failed(String),
}
```
with a single `is_settled() -> bool` method used by the sweep gate.
Wire compatibility
The on-disk / on-API format is preserved exactly via a custom Serialize/Deserialize that delegates to Display/FromStr:
The CRD's schema for the field still declares it as a plain string (custom `JsonSchema` impl pointing at `type: string`). Existing replicas in the field don't need migration; new operator code parses their existing status strings into the enum on read.
Why
The sweep-gate deadlock that #64 fixed was a missed match arm — the old `matches!(phase, None | Some("complete") | Some("partial"))` allow-list silently broke when `timeout-skipped` was added as a new terminal phase. That's exactly the class of bug the type system can catch: if the gate were written against an exhaustive match on the enum, the new variant would have surfaced as a compile error.
This PR doesn't change behaviour — #64 already fixed the deadlock — but it makes the next variant addition fail at compile time instead of in production. The new `is_settled()` method is the single canonical predicate; adding a new variant forces the author to think about whether it's settled-state or not.
Shape
Tests
5 new unit tests in `types/replica.rs::tests`:
Note
Stacks naturally with #64 but doesn't depend on it — refactor only, no behaviour change.